package service

import (
	"chat_demo/pkg/e"
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
	"go.mongodb.org/mongo-driver/bson/primitive"
	"gopkg.in/fatih/set.v0"
	"log"
	"net/http"
	"sync"
)

// SendMsg 发送消息的类型
type SendMsg struct {
	Type    int      `json:"type"`
	Message *Message `json:"message"`
}

// ReplyMsg 回复的消息
type ReplyMsg struct {
	From    string      `json:"from"`
	Code    int         `json:"code"`
	Content interface{} `json:"content"`
}

// Broadcast 广播类，包括广播内容和源用户
type Broadcast struct {
	Client  *Client
	Message []byte
	Type    int
}

type Message struct {
	FormId   string `json:"userID1"`
	TargetId string `json:"userID2"`
	Content  string `json:"content"`
}

// ClientManager 用户管理
type ClientManager struct {
	Clients    map[string]*Client
	Broadcast  chan *Broadcast
	Reply      chan *Client
	Register   chan *Client
	Unregister chan *Client
}

type Client struct {
	ID        string
	Conn      *websocket.Conn
	DataQueue chan []byte
	GroupSets set.Interface
}

var clientMap map[int64]*Client = make(map[int64]*Client, 0)

var rwLocker sync.RWMutex

var Manager = ClientManager{
	Clients:   make(map[string]*Client), // 参与连接的用户，出于性能的考虑，需要设置最大连接数
	Broadcast: make(chan *Broadcast),
	Register:  make(chan *Client),
	//Reply:      make(chan *Client),
	Unregister: make(chan *Client),
}

func WsHandler(c *gin.Context) {
	Id := c.Query("userID")
	//log.Println("接收到的 userID:", Id)
	//userId, _ := strconv.ParseInt(Id, 10, 64)
	isValida := true

	conn, err := (&websocket.Upgrader{
		CheckOrigin: func(r *http.Request) bool {
			return isValida
		},
	}).Upgrade(c.Writer, c.Request, nil)
	if err != nil {
		log.Println("升级为WebSocket连接失败:", err)
		return
	}
	//2.获取conn
	client := &Client{
		ID:        Id,
		Conn:      conn,
		DataQueue: make(chan []byte, 50),
		GroupSets: set.New(set.ThreadSafe),
	}
	//defer conn.Close()

	//rwLocker.Lock()
	//clientMap[userId] = client
	//rwLocker.Unlock()

	// 用户注册到用户管理上
	Manager.Register <- client

	go client.Read()
	go client.Write()
}

// 读取来自websocket里面的内容
func (c *Client) Read() {
	defer func() { // 避免忘记关闭，所以要加上close
		Manager.Unregister <- c
		_ = c.Conn.Close()
	}()
	for {
		//c.Conn.PongHandler()
		sendMsg := new(SendMsg)
		// _,msg,_:=c.Conn.ReadMessage()
		err := c.Conn.ReadJSON(&sendMsg) // 读取json格式，如果不是json格式，会报错
		if err != nil {
			log.Println("数据格式不正确", err)
			Manager.Unregister <- c
			_ = c.Conn.Close()
			break
		}
		if sendMsg.Type == 1 {
			if err != nil {
				log.Println("数据格式不正确", err)
				Manager.Unregister <- c
				_ = c.Conn.Close()
				break
			}
			log.Println(c.ID, "发送消息", sendMsg.Message.Content)
			// 将结构体转换为字节切片
			data, err := json.Marshal(sendMsg.Message)
			if err != nil {
				fmt.Println("Error:", err)
				return
			}
			Manager.Broadcast <- &Broadcast{
				Client:  c,
				Message: data,
			}
		} else if sendMsg.Type == 2 { //拉取历史消息
			//timeT, err := strconv.Atoi(sendMsg.Content) // 传送来时间
			//if err != nil {
			//	timeT = 999999999
			//}
			//results, _ := FindMany(conf.MongoDBName, c.SendID, c.ID, int64(timeT), 10)
			//if len(results) > 10 {
			//	results = results[:10]
			//} else if len(results) == 0 {
			//	replyMsg := ReplyMsg{
			//		Code:    e.WebsocketEnd,
			//		Content: "到底了",
			//	}
			//	msg, _ := json.Marshal(replyMsg)
			//	_ = c.Socket.WriteMessage(websocket.TextMessage, msg)
			//	continue
			//}
			//for _, result := range results {
			//	replyMsg := ReplyMsg{
			//		From:    result.From,
			//		Content: fmt.Sprintf("%s", result.Msg),
			//	}
			//	msg, _ := json.Marshal(replyMsg)
			//	_ = c.Socket.WriteMessage(websocket.TextMessage, msg)
			//}
		} else if sendMsg.Type == 3 { //获取所有未读信息
			//results, err := FirsFindtMsg(conf.MongoDBName, c.SendID, c.ID)
			//if err != nil {
			//	log.Println(err)
			//}
			//for _, result := range results {
			//	replyMsg := ReplyMsg{
			//		From:    result.From,
			//		Content: fmt.Sprintf("%s", result.Msg),
			//	}
			//	msg, _ := json.Marshal(replyMsg)
			//	_ = c.Socket.WriteMessage(websocket.TextMessage, msg)
			//}
		}
	}
}

// Write 向websocket发送消息，比如消息推送
func (c *Client) Write() {
	defer func() {
		_ = c.Conn.Close()
	}()

	for {
		select {
		case message, ok := <-c.DataQueue:
			if !ok {
				_ = c.Conn.WriteMessage(websocket.CloseMessage, []byte{})
				return
			}
			log.Println(c.ID, "接受消息:", string(message))
			var mes Message

			err := json.Unmarshal(message, &mes)
			if err != nil {
				fmt.Println("转换为目标结构体时出错:", err)
				return
			}
			replyMsg := ReplyMsg{
				Code:    e.WebsocketSuccessMessage,
				Content: mes,
			}
			msg, _ := json.Marshal(replyMsg)
			_ = c.Conn.WriteMessage(websocket.TextMessage, msg)
		}
	}

}

// ChatRoomList 获取聊天室列表
func ChatRoomList(c *gin.Context) {
	Id := c.Request.URL.Query().Get("userID")
	//userId, _ := strconv.ParseInt(Id, 10, 64)
	// 调用 findChatRoomsByUserID 函数获取聊天室列表
	chatRooms, err := findChatRoomsByUserID(MongoDB.Collection("ChatRoom"), Id)
	if err != nil {
		// 处理错误
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	// 返回 JSON 响应
	c.JSON(http.StatusOK, chatRooms)
}

// GetUnreadMessagesHandler 获取未读消息
func GetUnreadMessagesHandler(c *gin.Context) {
	chatRoomID := c.Param("chatRoomID")
	UserID := c.Param("UserID")
	// 将字符串转换为primitive.ObjectID类型
	chatRoomId, err := primitive.ObjectIDFromHex(chatRoomID)
	if err != nil {
		// 处理转换错误
		panic(err)
	}
	unreadMessages, err := getUnreadMessages(MongoDB, chatRoomId, UserID)
	if err != nil {
		// 处理错误
		fmt.Println(err)
	}
	// 返回 JSON 响应
	c.JSON(http.StatusOK, unreadMessages)

}

// GetChatRoomHistory 获取聊天室历史记录
func GetChatRoomHistory(c *gin.Context) {
	// 从路径参数中获取 chatRoomID
	chatRoomID := c.Param("chatRoomID")

	// 从查询参数中获取 timestamp
	timestamp := c.Param("timestamp")

	// 调用 getChatRoomHistory 方法获取历史消息
	historyMessages, err := getChatRoomHistory(MongoDB.Collection("ChatMessage"), chatRoomID, timestamp)
	if err != nil {
		// 处理错误
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	// 返回 JSON 响应
	c.JSON(http.StatusOK, historyMessages)
}
